//= require <http/UriResolver>

namespace("core.ClassLoader", {
	initialize : function(){
		this.readyState	= 0;
		this.status		= null;
		this.statusText	= null;
		this.headNode	= document.getElementsByTagName("head").item(0);
	},
	
	open : function( iMethod, iURL, iAsync) {
		this.method	= "GET";
		this.URL	= iURL;
	},
	
	send : function() {
		this.script = this.createScript(this.URL);
		var self   		    = this;
		var onLoad          = function() {
			self.status     = 200;
			self.statusText = "OK";
			self.readyState = 4;
			if ( self.onreadystatechange ) self.onreadystatechange();
		}
		var onReadyStateChange = function( iEvent ) {
			var e = (iEvent?iEvent:window.event).target?(iEvent?iEvent:window.event).target:(iEvent?iEvent:window.event).srcElement;
			if( e.readyState==="loaded" || e.readyState==="complete") onLoad();
		}
		if(navigator.product==="Gecko") this.script.onload = onLoad;
		else this.script.onreadystatechange = onReadyStateChange;
		
		this.headNode.appendChild(this.script);
		this.readyState = 1;
		if (this.onreadystatechange) this.onreadystatechange();
	
	},
	
	createScript : function(_src){
		var head   = document.getElementsByTagName("head").item(0);
		var scripts = head.getElementsByTagName("script");
		var script = document.createElement("script");
			script.setAttribute("type", "text/javascript");
			script.setAttribute("charset", (config.charset || "utf-8"));
			script.setAttribute("src", _src);
			return script;
	}
});


instance("core.ModuleLoader", {
    "@traits":[UriResolver],
    
	initialize : function(){
		window.cdn	  = this.cdn;
		var self	  = this;
		window.ensure = function(){self.download.apply(self,arguments)}
	},
	
	download : function(namespc, callback, uriresolver) {
        uriresolver = uriresolver;
		callback = callback || this.emptyFunc;
		(namespc instanceof Array) ?
			this.download_batch(namespc,callback, uriresolver): 
			this.download_only(namespc,callback, uriresolver);
	},
	
	download_batch : function(namespc, callback, uriresolver){
		var queue = namespc.slice(), self = this;
        function fileloaded(_ns){
	        self.downloaded[_ns] = true;
			delete queue[queue.indexOf(_ns)];
			queue=queue.clean();
			(queue.length<=0)? callback():null;};
            
		for(var i=0; i<=namespc.length-1; i++) {
			 	if(this.downloaded[namespc[i]]) 
					fileloaded(namespc[i]);
				else this.download_only(namespc[i],fileloaded, uriresolver);
		}
	},
	
	download_only : function(namespc, callback, uriresolver) {
		if(this.downloaded[namespc]) {return callback();}
		if(this.isloading(namespc))  {return this.queue(namespc, callback);}
		else this.queue(namespc,callback);

		var self = this;
        var classloaded = function(ns) {
            self.downloaded[ns] = true;
            var _callbacks = self.callbacks(ns);
            while(_callbacks && _callbacks.length > 0) {
          	   var f = _callbacks.pop();
                   f(ns);
            }
        };
		var xhr = new core.ClassLoader();
            xhr.ns = namespc;
            xhr.onreadystatechange = function() {
                if(this.readyState === 4) {
                    classloaded(xhr.ns);
                }
            };

            var url = uriresolver ? uriresolver(namespc) : this.resourcepath(namespc);
			if (namespc.indexOf("/") === 0) {url = namespc;};
            if(navigator.DeviceInfo.browser === "Opera" || !config.caching.enabled) {
                url = url + "?time=" + new Date().getTime();};
		    xhr.open("GET", url, true);
			xhr.send();
	},
	
	queue : function(namespc,callback){
		callback = callback || this.emptyFunc;
		if(!this.download_queue[namespc]) 
			this.download_queue[namespc] = [];
		this.download_queue[namespc].push(callback);
	},
	
	isloading : function(namespc) {
		 return (this.download_queue[namespc] && this.download_queue[namespc].length > 0);
	},
	
	callbacks : function(namespc) { 
	    return this.download_queue[namespc];
    },
	
    emptyFunc  		: function(){},
	
    downloaded 		: {},
    
    download_queue  : {}
	
//	cdn : function(filename){
//		if(config.cached_hosts && config.cached_hosts[filename]) {
//			return config.cached_hosts[filename];
//		}
//		else {
//			var hostindex = Math.round(Math.random()) * config.assethosts.length-1;
//			hostindex = (hostindex < 0) ? 0:hostindex;
//			if(!config.cached_hosts) config.cached_hosts = {};
//			config.cached_hosts[filename] = config.assethosts[hostindex] + config.loadpaths.images.replace("[classname]", this.getClassName()) + filename;
//			return config.cached_hosts[filename];
//		}
//	}
});

//Array.prototype.remove = function(from, to) {
//  var rest = this.slice((to || from) + 1 || this.length);
//  this.length = from < 0 ? this.length + from : from;
//  return this.push.apply(this, rest);
//};

Array.prototype.clean = function(){
		    var results = [];
		    for(var i=0; i<=this.length; i++) {
		        if(!this[i]) delete this[i];
		        else results.push(this[i])
		    }
		    return results;
		};